package com.rc.saas.tenant.controller.tenant;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageInfo;
import com.rc.saas.tenant.base.TenantBaseController;
import com.rc.saas.tenant.base.WebPageInfo;
import com.rc.saas.tenant.common.vo.TResponse;
import com.rc.saas.tenant.model.tenant.TenantRole;
import com.rc.saas.tenant.model.tenant.TenantRoleExample;
import com.rc.saas.tenant.model.tenant.TenantUser;
import com.rc.saas.tenant.model.tenant.TenantUserExample;
import com.rc.saas.tenant.search.tenant.TenantRoleSearch;
import com.rc.saas.tenant.service.tenant.TenantRoleService;
import com.rc.saas.tenant.service.tenant.TenantUserService;
import com.rc.saas.tenant.shiro.CustomRealm;
import com.rc.saas.tenant.shiro.ShiroUtils;
import com.rc.saas.tenant.util.ExportUtils;
import com.rc.saas.tenant.vo.tenant.TenantRoleDataAuthVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static java.lang.String.format;

/**
 * 角色管理
 */
@Controller
@RequestMapping("/tenant/role")
public class TenantRoleController extends TenantBaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private String prefix = "/templates/tenant/role";

    @Autowired
    private TenantRoleService tenantRoleService;

    @Autowired
    private TenantUserService tenantUserService;

    @Autowired
    private RedisTemplate redisTemplate;


    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Model model) {
        return prefix + "/role";
    }

    /**
     * 运营商角色分页
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/listPageTenantRole", method = RequestMethod.GET)
    public WebPageInfo listPageTenantRole(TenantRoleSearch tenantRoleSearch) {
        PageInfo<TenantRole> page = tenantRoleService.listPageTenantRole(tenantRoleSearch);
        WebPageInfo webPageInfo = new WebPageInfo(page.getList(), Long.valueOf(page.getTotal()).intValue());
        return webPageInfo;

    }


    /**
     * 导出平台角色列表
     */
    @ResponseBody
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public TResponse export(TenantRoleSearch tenantRoleSearch, HttpServletResponse response) {
        try {
            response.setHeader("Set-Cookie", "fileDownload=true; path=/");
            ExportUtils.setDefaultPaging(tenantRoleSearch);
            PageInfo<TenantRole> page = tenantRoleService.listPageTenantRole(tenantRoleSearch);
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("平台角色列表", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), TenantRole.class).sheet("平台角色列表").doWrite(page.getList());
            return null;
        } catch (Exception e) {
            logger.error("导出平台角色列表失败", e.getMessage());
            return TResponse.FAIL(e.getMessage());
        }
    }

    /**
     * 跳转至 新增运营商角色页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/addTenantRole", method = RequestMethod.GET)
    public String addTenantRole(Model model) {
        return prefix + "/addTenantRole";
    }

    /**
     * 跳转至 编辑页面
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping(value = "/editRole/{id}", method = RequestMethod.GET)
    public String editRole(@PathVariable("id") Long id, Model model) {
        TenantRole role = tenantRoleService.selectByPrimaryKey(id);
        model.addAttribute("role", role);
        return prefix + "/editRole";
    }

    /**
     * @param tenantRoleId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/listDataAuth", method = RequestMethod.GET)
    public TResponse listDataAuth(Long tenantRoleId) {
        TenantRole role = tenantRoleService.selectByPrimaryKey(tenantRoleId);
//        String auth = format("%03d", role.getDataAuth());
        String auth = role.getDataAuth();

        TenantRoleDataAuthVo platformAuth = new TenantRoleDataAuthVo();
        platformAuth.setName("平台权限");
        platformAuth.setValue("100");
        String isPlatformAuth = auth.substring(0, 1);
        if ("1".equals(isPlatformAuth)) {
            platformAuth.setSelected(true);
        }

        TenantRoleDataAuthVo operatorAuth = new TenantRoleDataAuthVo();
        operatorAuth.setName("加盟商权限");
        operatorAuth.setValue("10");
        String isOperatorAuth = auth.substring(1, 2);
        if ("1".equals(isOperatorAuth)) {
            operatorAuth.setSelected(true);
        }

        TenantRoleDataAuthVo enterpriseAuth = new TenantRoleDataAuthVo();
        enterpriseAuth.setName("企业权限");
        enterpriseAuth.setValue("1");
        String isEnterpriseAuth = auth.substring(2, 3);
        if ("1".equals(isEnterpriseAuth)) {
            enterpriseAuth.setSelected(true);
        }

        ArrayList<TenantRoleDataAuthVo> list = new ArrayList<>();
        list.add(platformAuth);
        list.add(operatorAuth);
        list.add(enterpriseAuth);
        return TResponse.SUCCESS_DATA(list);
    }

    /**
     * 保存分配权限
     *
     * @param
     * @param
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/saveDataAuth", method = RequestMethod.POST)
    public TResponse saveDataAuth(Long tenantRoleId, String dataAuthList) {
        try {
            List<Integer> dataAuths = Arrays.asList(dataAuthList.split(",")).stream().map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
            Integer sum = dataAuths.stream().reduce(Integer::sum).orElse(0);
            String dataAuth = format("%03d", sum);
            TenantRole tenantRole = new TenantRole();
//            tenantRole.setDataAuth(sum.longValue());
            tenantRole.setDataAuth(dataAuth);
            tenantRole.setTenantRoleId(tenantRoleId);
//            TenantRoleExample tenantRoleExample = new TenantRoleExample();
//            tenantRoleExample.createCriteria().andTenantRoleIdEqualTo(tenantRoleId);

            tenantRoleService.updateByPrimaryKeySelective(tenantRole);
        } catch (Exception e) {
            logger.info("保存数据权限失败,tenantRoleId:{}", tenantRoleId);
            return TResponse.FAIL("保存数据权限失败");
        }

        return TResponse.SUCCESS();
    }

    /**
     * 跳转至 查看页面
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping(value = "/checkRole/{id}", method = RequestMethod.GET)
    public String checkRole(@PathVariable("id") Long id, Model model) {
        TenantRole role = tenantRoleService.selectByPrimaryKey(id);
        model.addAttribute("role", role);
        return prefix + "/checkRole";
    }

    /**
     * 保存
     *
     * @param request
     * @param role
     * @return
     */
    @ResponseBody()
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public TResponse save(HttpServletRequest request, TenantRole role) {
        TenantUser user = ShiroUtils.getSessionUser();
        role.setTenantCode(user.getTenantCode());
        if (role.getTenantRoleId() != null) {
            //更新角色，删除缓存中的角色
            if (redisTemplate.hasKey("shiro:" + user.getTenantCode() + ":" + role.getTenantRoleId())) {
                redisTemplate.delete("shiro:" + user.getTenantCode() + ":" + role.getTenantRoleId());
            }
            tenantRoleService.updateRole(role);
        } else {
            tenantRoleService.createRole(role, user);
        }
        return TResponse.SUCCESS();
    }

    /**
     * 重新赋值权限(在比如:给一个角色临时添加一个权限,需要调用此方法刷新权限,否则还是没有刚赋值的权限)
     */
    //public static void reloadAuthorizing(MyRealm myRealm, String username) {
    //    Subject subject = SecurityUtils.getSubject();
    //    String realmName = subject.getPrincipals().getRealmNames().iterator().next();
    //    //第一个参数为用户名,第二个参数为realmName,test想要操作权限的用户
    //    SimplePrincipalCollection principals = new SimplePrincipalCollection(username, realmName);
    //    subject.runAs(principals);
    //    myRealm.getAuthorizationCache().remove(subject.getPrincipals());
    //    subject.releaseRunAs();
    //}
    public void reload() {
        RedisSessionDAO sessionDAO = (RedisSessionDAO) getBean("redisSessionDAO");    //然后就这样就可以获取 Spring托管的bean了
        Collection<Session> ss = sessionDAO.getActiveSessions();// 获取在线用户信息 下面的代码封装成list，好做分页查询功能
        for (Session s : ss) {
            Object obj = s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            if (obj != null) {
                SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
                if (spc.getPrimaryPrincipal() != null) {
                    TenantUser u = (TenantUser) spc.getPrimaryPrincipal();// 转成User
                    logger.info("TenantUser.........{}", u.getLoginName());

                    //m.put("user", u);
                }
            }

            //list.add(m);// 装成list，好做分页查询功能
        }


        //add by jizhun at 重新修改权限后清楚缓存，调用doGetAuthorizationInfo重新取角色的权限信息
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        CustomRealm realm = (CustomRealm) rsm.getRealms().iterator().next();
        Subject subject = SecurityUtils.getSubject();
        String realmName = subject.getPrincipals().getRealmNames().iterator().next();
        logger.info("oper.user.........login.user=" + SecurityUtils.getSubject().getPrincipal().toString());

        //shiroRealm.clearAllCachedAuthorizationInfo2();//清楚所有用户权限
        //第一个参数为用户名,第二个参数为realmName,test想要操作权限的用户
        SimplePrincipalCollection principals = new SimplePrincipalCollection("test", realmName);
        subject.runAs(principals);

        TenantUser user = new TenantUser();
        user.setTenantUserId(7L);

        realm.getAuthenticationCache().remove(user);
        realm.getAuthorizationCache().remove(user);
        //realm.getAuthorizationCache().remove("admin_shiro_redis_cache:authenticationCache:test");
        subject.releaseRunAs();
    }

    /**
     * 删除
     *
     * @param request
     * @param id
     * @return
     */
    @RequestMapping(value = "/remove", method = RequestMethod.POST)
    @ResponseBody
    public TResponse remove(HttpServletRequest request, Long id) {
        try {
            TenantUserExample tenantUserExample = new TenantUserExample();
            tenantUserExample.createCriteria().andTenantRoleIdEqualTo(id);
            long count = tenantUserService.countByExample(tenantUserExample);
            if (count > 0) {
                return TResponse.FAIL("有账户关联该角色，角色删除失败");
            }
            tenantRoleService.deleteByPrimaryKey(id);
        } catch (Exception e) {
            return TResponse.FAIL("操作失败");
        }
        return TResponse.SUCCESS();
    }

    @ResponseBody
    @RequestMapping(value = "/updateRoleStatus", method = RequestMethod.POST)
    public TResponse updateRoleStatus(Long id, String status) {
        TenantRole role = tenantRoleService.selectByPrimaryKey(id);
        role.setStatus(status);
        tenantRoleService.updateByPrimaryKeySelective(role);
        return TResponse.SUCCESS();
    }
}
